package com.idc.resource.service;

import com.idc.resource.dal.dto.TCompanyInfo;
import com.idc.resource.dal.dto.TUserInfo;
import com.idc.resource.enums.AuthCodeEnum;
import com.idc.resource.enums.AuthStatusEnum;
import com.idc.resource.enums.ErrorCodeEnum;
import com.idc.resource.enums.UserLevelEnum;
import com.idc.resource.exception.IdcServiceException;
import com.idc.resource.help.EmailHelp;
import com.idc.resource.help.RedisHelp;
import com.idc.resource.help.SmsMsgHelp;
import com.idc.resource.help.model.AuthCodeConfig;
import com.idc.resource.help.model.EmailMsg;
import com.idc.resource.help.model.SmsMsgInfo;
import com.idc.resource.manager.CompanyManager;
import com.idc.resource.manager.UserManager;
import com.idc.resource.model.AuthCodeInfo;
import com.idc.resource.model.UserInfoResDto;
import com.idc.resource.util.CacheKeyUtils;
import com.idc.resource.util.RandomCodeUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;

/**
 * 验证码服务
 * Created by Administrator on 2017/7/15 0015.
 */
@Slf4j
@Service
public class AuthCodeService {

    /** 用户管理 */
    private final UserManager userManager;
    /** 验证码配置 */
    private final AuthCodeConfig authCodeConfig;
    /** redis */
    private final RedisHelp redisHelp;
    /** 邮件服务 */
    private final EmailHelp emailHelp;
    /** 企业信息管理 */
    private final CompanyManager companyManager;
    /** 短信验证码服务 */
    private final SmsMsgHelp smsMsgHelp;

    @Autowired
    public AuthCodeService(AuthCodeConfig authCodeConfig, RedisHelp redisHelp, UserManager userManager, EmailHelp emailHelp, CompanyManager companyManager, SmsMsgHelp smsMsgHelp) {
        this.authCodeConfig = authCodeConfig;
        this.redisHelp = redisHelp;
        this.userManager = userManager;
        this.emailHelp = emailHelp;
        this.companyManager = companyManager;
        this.smsMsgHelp = smsMsgHelp;
    }

    /**
     *  获取验证码
     * @param authCodeEnum 验证码类型
     * @param authCodeInfo 不带验证码的用户信息
     */
    private void getAuthCode(AuthCodeEnum authCodeEnum,AuthCodeInfo authCodeInfo){
        long timeOut = authCodeConfig.getTime()*60;
        authCodeInfo.setAuthCode(buildAuthCode());
        if(AuthCodeEnum.EMAIL.getCode().equals(authCodeEnum.getCode())) {
            redisHelp.insertObject(CacheKeyUtils.buildEmailAuthKey(authCodeInfo.getToken()), authCodeInfo,timeOut);
        }else {
            redisHelp.insertObject(CacheKeyUtils.buildMsgAuthKey(authCodeInfo.getToken()), authCodeInfo,timeOut);
        }
    }

    /**
     * 获取验证码
     * @param authCodeEnum 验证码类型
     * @param authCodeInfo 不带验证码的用户信息
     * @return 验证结果 true成功 false 失败
     */
    public Boolean authCode(AuthCodeEnum authCodeEnum,AuthCodeInfo authCodeInfo){
        String key = CacheKeyUtils.buildEmailAuthKey(authCodeInfo.getToken());

        if(AuthCodeEnum.SMS_MSG.getCode().equals(authCodeEnum.getCode())) {
            key =CacheKeyUtils.buildMsgAuthKey(authCodeInfo.getToken());
        }
        AuthCodeInfo cacheCode =redisHelp.queryObjectByKey(key, AuthCodeInfo.class);
        if(cacheCode==null){
            throw new IdcServiceException(ErrorCodeEnum.AUTH_CODE_LOSE.getCode(),ErrorCodeEnum.AUTH_CODE_LOSE.getDesc());
        }
        if(!cacheCode.auth(authCodeInfo,authCodeConfig.getIgnoreCase())){
            log.error("缓存中验证码信息:{},用户请求验证码信息:{},对比不一致",cacheCode,authCodeInfo);
            throw new IdcServiceException(ErrorCodeEnum.AUTH_CODE_ERROR.getCode(),ErrorCodeEnum.AUTH_CODE_ERROR.getDesc());
        }
        updateUser(authCodeEnum,cacheCode);
        redisHelp.deleteObject(key);
        return true;
    }

    /**
     * 构建验证码
     * @return 验证码
     */
    private String buildAuthCode(){
        String authCode;
        if(authCodeConfig.getIsNum()) {
            authCode = RandomCodeUtil.buildCode(authCodeConfig.getLength());
        }else {
            authCode = RandomCodeUtil.buildNumCode(authCodeConfig.getLength());
        }
        return authCode;
    }

    /**
     * 验证完成后更新用户验证状态
     * @param authCodeEnum 验证类型枚举
     * @param authCodeInfo 验证信息
     */
    private void updateUser(AuthCodeEnum authCodeEnum,AuthCodeInfo authCodeInfo){
        TUserInfo userInfo = new TUserInfo();
        userInfo.setId(authCodeInfo.getId());
        if(AuthCodeEnum.EMAIL.getCode().equals(authCodeEnum.getCode())) {
            userInfo.setEmailAuth(AuthStatusEnum.AUTH.getCode());
        }
        if(AuthCodeEnum.SMS_MSG.getCode().equals(authCodeEnum.getCode())) {
            userInfo.setPhoneAuth(AuthStatusEnum.AUTH.getCode());
        }
        userManager.updateUser(userInfo);
    }

    /**
     * 验证码发送
     * @param authCodeEnum 验证码类型
     * @param authCodeInfo 验证码发送请求
     * @return 发送结果 true 成功
     */
    public Boolean sendAuthCode(AuthCodeEnum authCodeEnum,AuthCodeInfo authCodeInfo){
        UserInfoResDto userInfoResDto = redisHelp.queryObjectByKey(authCodeInfo.getToken(),UserInfoResDto.class);
        if(userInfoResDto==null){
            log.error("登录已经失效，无法操作");
            throw new IdcServiceException(ErrorCodeEnum.LOGIN_LOSE.getCode(),ErrorCodeEnum.LOGIN_LOSE.getDesc());
        }
        try {
            TUserInfo tUserInfo = userManager.selectById(userInfoResDto.getId());
            if(AuthCodeEnum.EMAIL.getCode().equals(authCodeEnum.getCode())){
                if(UserLevelEnum.NORMAL.getCode().equals(tUserInfo.getUserLv())){
                    log.error("普通用户无法进行企业邮箱认证");
                    throw new IdcServiceException(ErrorCodeEnum.AUTH_ERROR.getCode(),ErrorCodeEnum.AUTH_ERROR.getDesc());
                }
                TCompanyInfo tCompanyInfo = companyManager.selectById(tUserInfo.getCompanyId());
                return sendEmailAuth(userInfoResDto,tCompanyInfo.getCompanyEmail());
            }
            return sendMsgAuth(userInfoResDto);
        }catch (IdcServiceException ise){
            throw ise;
        }catch (Exception e){
            log.error("验证码发送失败，系统异常:",e);
            throw new IdcServiceException(ErrorCodeEnum.SYSTEM_ERROR.getCode(),ErrorCodeEnum.SYSTEM_ERROR.getDesc());
        }

    }

    /**
     * 发送邮件验证
     * @param userInfo 用户信息
     * @param email 收件人邮箱
     * @return 发送结果
     */
     boolean sendEmailAuth(UserInfoResDto userInfo,String email){
        AuthCodeInfo authCodeInfo = new AuthCodeInfo();
        authCodeInfo.setUserId(userInfo.getUserId());
        authCodeInfo.setId(userInfo.getId());
        authCodeInfo.setToken(userInfo.getToken());
        getAuthCode(AuthCodeEnum.EMAIL,authCodeInfo);
        Map<String,String> tempMap = new HashMap<>();
        tempMap.put("name","");
        tempMap.put("code",authCodeInfo.getAuthCode());
        EmailMsg emailMsg = new EmailMsg();
        emailMsg.setReceiverMail(email);
        emailMsg.setMsg(emailHelp.buildMsgByTemp(tempMap));
        return emailHelp.sendEmail(emailMsg);
    }

    /**
     * 发送邮件验证
     * @param userInfo 用户信息
     * @return 发送结果
     */
    private boolean sendMsgAuth(UserInfoResDto userInfo){
        AuthCodeInfo authCodeInfo = new AuthCodeInfo();
        authCodeInfo.setUserId(userInfo.getUserId());
        authCodeInfo.setId(userInfo.getId());
        authCodeInfo.setToken(userInfo.getToken());
        getAuthCode(AuthCodeEnum.SMS_MSG,authCodeInfo);
        SmsMsgInfo smsMsgInfo = new SmsMsgInfo();
        smsMsgInfo.setPhoneNum(userInfo.getPhone());
        smsMsgInfo.setAuthCode(authCodeInfo.getAuthCode());
        return smsMsgHelp.sendAuthCodeMsg(smsMsgInfo);
    }

}
